/*
 * Copyright 2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mx.ymate.security.impl;

import com.mx.ymate.dev.result.MxResult;
import com.mx.ymate.security.ISecurity;
import com.mx.ymate.security.ISecurityConfig;
import com.mx.ymate.security.base.code.SecurityCode;
import com.mx.ymate.security.handler.ILoginHandler;
import com.mx.ymate.security.handler.IUserHandler;
import net.ymate.platform.commons.util.ClassUtils;
import net.ymate.platform.core.configuration.IConfigReader;
import net.ymate.platform.core.module.IModuleConfigurer;

/**
 * DefaultSaTokenConfig generated By ModuleMojo on 2022/07/03 12:39
 *
 * @author YMP (https://www.ymate.net/)
 */
public final class DefaultSecurityConfig implements ISecurityConfig {

    private boolean enabled;

    /**
     * 客户端名称
     */
    private String client;

    /**
     * loginHandler实现类
     */
    private ILoginHandler loginHandlerClass;

    /**
     * userHandler实现类
     */
    private IUserHandler userHandlerClass;

    /**
     * 验证错误N次后锁定账户  默认不锁定  -1不锁定
     */
    private int errorCount;

    /**
     * 是否开启日志记录 默认false
     */
    private boolean openLog;

    /**
     * 登录拦截排除的路径用|分割
     */
    private String excludePathPatterns;

    private boolean initialized;

    public static DefaultSecurityConfig defaultConfig() {
        return builder().build();
    }

    public static DefaultSecurityConfig create(IModuleConfigurer moduleConfigurer) {
        return new DefaultSecurityConfig(moduleConfigurer);
    }


    public static Builder builder() {
        return new Builder();
    }

    private DefaultSecurityConfig() {
    }


    private DefaultSecurityConfig(IModuleConfigurer moduleConfigurer) {
        IConfigReader configReader = moduleConfigurer.getConfigReader();
        enabled = configReader.getBoolean(ENABLED, true);
        client = configReader.getString(CLIENT, "default");
        String loginHandlerClassName = configReader.getString(LOGIN_HANDLER_CLASS, ILoginHandler.DefaultLoginHandler.class.getName());
        loginHandlerClass = ClassUtils.impl(loginHandlerClassName, ILoginHandler.class, this.getClass());
        String userHandlerClassName = configReader.getString(USER_HANDLER_CLASS, IUserHandler.DefaultUserHandler.class.getName());
        userHandlerClass = ClassUtils.impl(userHandlerClassName, IUserHandler.class, this.getClass());
        errorCount = configReader.getInt(ERROR_COUNT, -1);
        openLog = configReader.getBoolean(OPEN_LOG, false);
        excludePathPatterns = configReader.getString(EXCLUDE_PATH_PATTERNS, excludePathPatterns);
        //
        // TODO What to do?
    }

    @Override
    public void initialize(ISecurity owner) throws Exception {
        if (!initialized) {
            if (enabled) {
                // TODO What to do?
            }
            initialized = true;
        }
    }

    @Override
    public boolean isInitialized() {
        return initialized;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    @Override
    public String client() {
        return client;
    }

    @Override
    public ILoginHandler loginHandlerClass() {
        return loginHandlerClass;
    }

    @Override
    public IUserHandler userHandlerClass() {
        return userHandlerClass;
    }

    @Override
    public int errorCount() {
        return errorCount;
    }

    @Override
    public boolean openLog() {
        return openLog;
    }

    @Override
    public String excludePathPatterns() {
        return excludePathPatterns;
    }

    @Override
    public boolean error(MxResult mxResult) {
        return mxResult == null || SecurityCode.SECURITY_CHECK_ERROR.code().equals(mxResult.code());
    }


    public void setEnabled(boolean enabled) {
        if (!initialized) {
            this.enabled = enabled;
        }
    }


    public void setInitialized(boolean initialized) {
        this.initialized = initialized;
    }

    public void setClient(String client) {
        if (!initialized) {
            this.client = client;
        }
    }

    public void setLoginHandlerClass(ILoginHandler loginHandlerClass) {
        if (!initialized) {
            this.loginHandlerClass = loginHandlerClass;
        }
    }

    public void setUserHandlerClass(IUserHandler userHandlerClass) {
        if (!initialized) {
            this.userHandlerClass = userHandlerClass;
        }
    }

    public void setErrorCount(int errorCount) {
        if (!initialized) {
            this.errorCount = errorCount;
        }
    }

    public void setOpenLog(boolean openLog) {
        if (!initialized) {
            this.openLog = openLog;
        }
    }

    public void setExcludePathPatterns(String excludePathPatterns) {
        if (!initialized) {
            this.excludePathPatterns = excludePathPatterns;
        }
    }

    public static final class Builder {

        private final DefaultSecurityConfig config = new DefaultSecurityConfig();

        private Builder() {
        }

        public Builder enabled(boolean enabled) {
            config.setEnabled(enabled);
            return this;
        }

        public Builder client(String client) {
            config.setClient(client);
            return this;
        }

        public Builder loginHandlerClass(ILoginHandler loginHandlerClass) {
            config.setLoginHandlerClass(loginHandlerClass);
            return this;
        }

        public Builder userHandlerClass(IUserHandler userHandlerClass) {
            config.setUserHandlerClass(userHandlerClass);
            return this;
        }

        public Builder maxLoginCount(int errorCount) {
            config.setErrorCount(errorCount);
            return this;
        }

        public Builder openLog(boolean openLog) {
            config.setOpenLog(openLog);
            return this;
        }

        public Builder excludePathPatterns(String excludePathPatterns) {
            config.setExcludePathPatterns(excludePathPatterns);
            return this;
        }

        public DefaultSecurityConfig build() {
            return config;
        }
    }
}